package com.proto {
	/**
	 * ...
	 * @author chenlong 2017/5/27 14:19
	 */
	public class ProtoBuf {
		
		public static const VERSION:String = "5.0.1";
		//public static var ByteBuffer = ByteBuffer;
		//public static var Long = Long || null;
		
		public static const WIRE_TYPES:Object = {"VARINT":0, "BITS64":1, "LDELIM":2, "STARTGROUP":3, "ENDGROUP":4, "BITS32":5};
		
		//public static var builder:Builder = Builder;
		
		public static const PACKABLE_WIRE_TYPES:Array = [
			ProtoBuf.WIRE_TYPES.VARINT,
			ProtoBuf.WIRE_TYPES.BITS64,
			ProtoBuf.WIRE_TYPES.BITS32
		];
		
		public static const TYPES:Object = {
			// According to the protobuf spec.
			"int32": {
				name: "int32",
				wireType: ProtoBuf.WIRE_TYPES.VARINT,
				defaultValue: 0
			},
			"uint32": {
				name: "uint32",
				wireType: ProtoBuf.WIRE_TYPES.VARINT,
				defaultValue: 0
			},
			"sint32": {
				name: "sint32",
				wireType: ProtoBuf.WIRE_TYPES.VARINT,
				defaultValue: 0
			},
			"int64": {
				name: "int64",
				wireType: ProtoBuf.WIRE_TYPES.VARINT,
				defaultValue:undefined// ProtoBuf.Long ? ProtoBuf.Long.ZERO : undefined
			},
			"uint64": {
				name: "uint64",
				wireType: ProtoBuf.WIRE_TYPES.VARINT,
				defaultValue: undefined//ProtoBuf.Long ? ProtoBuf.Long.UZERO : undefined
			},
			"sint64": {
				name: "sint64",
				wireType: ProtoBuf.WIRE_TYPES.VARINT,
				defaultValue: undefined//ProtoBuf.Long ? ProtoBuf.Long.ZERO : undefined
			},
			"bool": {
				name: "bool",
				wireType: ProtoBuf.WIRE_TYPES.VARINT,
				defaultValue: false
			},
			"double": {
				name: "double",
				wireType: ProtoBuf.WIRE_TYPES.BITS64,
				defaultValue: 0
			},
			"string": {
				name: "string",
				wireType: ProtoBuf.WIRE_TYPES.LDELIM,
				defaultValue: ""
			},
			"bytes": {
				name: "bytes",
				wireType: ProtoBuf.WIRE_TYPES.LDELIM,
				defaultValue: null // overridden in the code, must be a unique instance
			},
			"fixed32": {
				name: "fixed32",
				wireType: ProtoBuf.WIRE_TYPES.BITS32,
				defaultValue: 0
			},
			"sfixed32": {
				name: "sfixed32",
				wireType: ProtoBuf.WIRE_TYPES.BITS32,
				defaultValue: 0
			},
			"fixed64": {
				name: "fixed64",
				wireType: ProtoBuf.WIRE_TYPES.BITS64,
				defaultValue: undefined// ProtoBuf.Long ? ProtoBuf.Long.UZERO : undefined
			},
			"sfixed64": {
				name: "sfixed64",
				wireType: ProtoBuf.WIRE_TYPES.BITS64,
				defaultValue:undefined// ProtoBuf.Long ? ProtoBuf.Long.ZERO : undefined
			},
			"float": {
				name: "float",
				wireType: ProtoBuf.WIRE_TYPES.BITS32,
				defaultValue: 0
			},
			"enum": {
				name: "enum",
				wireType: ProtoBuf.WIRE_TYPES.VARINT,
				defaultValue: 0
			},
			"message": {
				name: "message",
				wireType: ProtoBuf.WIRE_TYPES.LDELIM,
				defaultValue: null
			},
			"group": {
				name: "group",
				wireType: ProtoBuf.WIRE_TYPES.STARTGROUP,
				defaultValue: null
			}
		};
		
		public static const MAP_KEY_TYPES:Array = [
			ProtoBuf.TYPES["int32"],
			ProtoBuf.TYPES["sint32"],
			ProtoBuf.TYPES["sfixed32"],
			ProtoBuf.TYPES["uint32"],
			ProtoBuf.TYPES["fixed32"],
			ProtoBuf.TYPES["int64"],
			ProtoBuf.TYPES["sint64"],
			ProtoBuf.TYPES["sfixed64"],
			ProtoBuf.TYPES["uint64"],
			ProtoBuf.TYPES["fixed64"],
			ProtoBuf.TYPES["bool"],
			ProtoBuf.TYPES["string"],
			ProtoBuf.TYPES["bytes"]
		];
		
		public static const ID_MIN:uint = 1;
		
		public static const ID_MAX:uint = 0x1FFFFFFF;
		
		public static var convertFieldsToCamelCase:Boolean = false;
		
		public static var populateAccessors:Boolean = true;
		
		public static var populateDefaults:Boolean = true;
		
		public static var util:ProtoUtil = new ProtoUtil();
		
		public static function loadProto( protoContents:String , builder:* = null , filename:* = null):*{
			
			if ( builder is String || (builder && builder["file"] is String && builder["root"] is String)){				
				filename = builder;
				builder = undefined;
			}
			
			var o:MetaProto2 = Parser.parse( protoContents );
			
			return ProtoBuf.loadJson( o , builder, filename );//ProtoBuf.DotProto.Parser.parse(proto)
		}
		
		/**
		 * Loads a .json definition and returns the Builder.
		 * @param {!*|string} json JSON definition
		 * @param {(ProtoBuf.Builder|string|{root: string, file: string})=} builder Builder to append to. Will create a new one if omitted.
		 * @param {(string|{root: string, file: string})=} filename The corresponding file name if known. Must be specified for imports.
		 * @return {ProtoBuf.Builder} Builder to create new messages
		 * @throws {Error} If the definition cannot be parsed or built
		 */
		public static function loadJson( json:* , builder:* , filename:* ):*{
			
			if ( builder is String || (builder && builder["file"] is String && builder["root"] is String)){
				
				filename = builder;
				builder = null;
			}
			if (!builder || !(builder is Object) )
				builder = ProtoBuf.newBuilder();
			if (json is String)
				json = JSON.parse(json);
			//builder["import"](json, filename);
			//builder.resolveAll();
			return builder;
		}
		
		public static function newBuilder( options:Object = null ):*{
			
			options = options || {};
			if (options['convertFieldsToCamelCase'] === undefined)
				options['convertFieldsToCamelCase'] = ProtoBuf.convertFieldsToCamelCase;
			if (options['populateAccessors'] === undefined)
				options['populateAccessors'] = ProtoBuf.populateAccessors;
			return null;// new Builder( options );// ProtoBuf.builder(options);
		}
	}

}